///*
// * Copyright (c) 2018-2022 Caratacus, (caratacus@qq.com).
// *
// * Permission is hereby granted, free of charge, to any person obtaining a copy of
// * this software and associated documentation files (the "Software"), to deal in
// * the Software without restriction, including without limitation the rights to
// * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// * the Software, and to permit persons to whom the Software is furnished to do so,
// * subject to the following conditions:
// *
// * The above copyright notice and this permission notice shall be included in all
// * copies or substantial portions of the Software.
// *
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// */
//package com.learn.autoconfigure;
//
//import java.lang.reflect.Type;
//import java.nio.charset.StandardCharsets;
//import java.util.Arrays;
//import java.util.List;
//import java.util.Objects;
//
//import com.learn.common.annotation.UnifiedReturn;
//import com.learn.common.cons.APICons;
//import com.learn.common.interceptors.ApiInterceptor;
//import com.learn.common.undertow.UndertowServerFactoryCustomizer;
//import com.learn.framework.responses.ApiResponses;
//import com.learn.framework.spring.ApplicationUtils;
//import com.learn.framework.spring.Crown2HandlerExceptionResolver;
//import com.learn.framework.spring.enums.IEnumConverterFactory;
//import com.learn.framework.spring.validator.ValidatorCollectionImpl;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.MethodParameter;
//import org.springframework.format.FormatterRegistry;
//import org.springframework.http.HttpInputMessage;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
//import org.springframework.http.converter.HttpMessageConverter;
//import org.springframework.http.converter.StringHttpMessageConverter;
//import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
//import org.springframework.http.server.ServerHttpRequest;
//import org.springframework.http.server.ServerHttpResponse;
//import org.springframework.validation.Validator;
//import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
//import org.springframework.web.bind.annotation.ControllerAdvice;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.RestController;
//import org.springframework.web.context.request.RequestContextListener;
//import org.springframework.web.servlet.HandlerExceptionResolver;
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
//import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
//
//import com.alibaba.fastjson.serializer.SerializerFeature;
//import com.alibaba.fastjson.support.config.FastJsonConfig;
//import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
//
//import io.undertow.Undertow;
//
///**
// * <p>
// * Spring Boot 配置
// * </p>
// *
// * @author Caratacus
// */
//@Configuration
//public class WebMvcAutoConfiguration implements WebMvcConfigurer {
//
//    @Override
//    public Validator getValidator() {
//        return new SpringValidatorAdapter(new ValidatorCollectionImpl());
//    }
//
//    @Override
//    public void addFormatters(FormatterRegistry registry) {
//        registry.addConverterFactory(new IEnumConverterFactory());
//    }
//
//    @Bean
//    @ConditionalOnClass(Undertow.class)
//    public UndertowServerFactoryCustomizer undertowServerFactoryCustomizer() {
//        return new UndertowServerFactoryCustomizer();
//    }
//
//    @Bean
//    @ConditionalOnMissingBean(RequestContextListener.class)
//    public RequestContextListener requestContextListener() {
//        return new RequestContextListener();
//    }
//
//    @Override
//    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//        converters.removeIf(e -> e instanceof MappingJackson2HttpMessageConverter);
//        converters.removeIf(e -> e instanceof StringHttpMessageConverter);
//        StringHttpMessageConverter stringMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
//        FastJsonHttpMessageConverter jsonMessageConverter = new FastJsonHttpMessageConverter();
//        FastJsonConfig jsonConfig = new FastJsonConfig();
//        List<MediaType> supportedMediaTypes = Arrays.asList(
//                MediaType.APPLICATION_JSON,
//                MediaType.APPLICATION_JSON_UTF8,
//                MediaType.APPLICATION_ATOM_XML,
//                MediaType.APPLICATION_FORM_URLENCODED,
//                MediaType.APPLICATION_OCTET_STREAM,
//                MediaType.APPLICATION_PDF,
//                MediaType.APPLICATION_RSS_XML,
//                MediaType.APPLICATION_XHTML_XML,
//                MediaType.APPLICATION_XML,
//                MediaType.IMAGE_GIF,
//                MediaType.IMAGE_JPEG,
//                MediaType.IMAGE_PNG,
//                MediaType.TEXT_EVENT_STREAM,
//                MediaType.TEXT_HTML,
//                MediaType.TEXT_MARKDOWN,
//                MediaType.TEXT_PLAIN,
//                MediaType.TEXT_XML);
//        jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
//        jsonConfig.setSerializerFeatures(SerializerFeature.SortField, SerializerFeature.WriteEnumUsingToString, SerializerFeature.QuoteFieldNames, SerializerFeature.SkipTransientField, SerializerFeature.BrowserCompatible, SerializerFeature.DisableCircularReferenceDetect);
//        jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
//        jsonMessageConverter.setFastJsonConfig(jsonConfig);
//        jsonMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
//        converters.add(jsonMessageConverter);
//        converters.add(stringMessageConverter);
//    }
//
//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new ApiInterceptor()).addPathPatterns("/**");
//    }
//
//    @Override
//    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
//        exceptionResolvers.add(new Crown2HandlerExceptionResolver());
//    }
//
//    @ControllerAdvice("com.learn")
//    static class CommonControllerAdvice implements RequestBodyAdvice, ResponseBodyAdvice {
//
//        @Override
//        public boolean supports(MethodParameter returnType, Class converterType) {
//            RestController restController = returnType.getDeclaringClass().getAnnotation(RestController.class);
//            ResponseBody responseBody = returnType.getMethodAnnotation(ResponseBody.class);
//            boolean wrapper = true;
//            UnifiedReturn unifiedReturn = returnType.getMethodAnnotation(UnifiedReturn.class);
//            if (Objects.nonNull(unifiedReturn)) {
//                wrapper = unifiedReturn.wrapper();
//            }
//            return (Objects.nonNull(restController) || Objects.nonNull(responseBody)) && wrapper;
//        }
//
//        @Override
//        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//            UnifiedReturn unifiedReturn = returnType.getMethodAnnotation(UnifiedReturn.class);
//            HttpStatus status = HttpStatus.OK;
//            if (Objects.nonNull(unifiedReturn)) {
//                status = unifiedReturn.status();
//            }
//            return body instanceof ApiResponses ? body : ApiResponses.<Object>success(response, status, body);
//        }
//
//        @Override
//        public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//            return true;
//        }
//
//        @Override
//        public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//            return inputMessage;
//        }
//
//        @Override
//        public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//            ApplicationUtils.getRequest().setAttribute(APICons.API_REQUEST_BODY, body);
//            return body;
//        }
//
//        @Override
//        public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
//            return body;
//        }
//    }
//
//}
